home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 18
/
CU Amiga Magazine's Super CD-ROM 18 (1997)(EMAP Images)(GB)[!][issue 1998-01].iso
/
CUCD
/
Magazine
/
C_Tutorial
/
Part-6
/
asl1a.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-10-27
|
19KB
|
760 lines
#include "iff.h"
#include<exec/libraries.h>
#include<intuition/intuition.h>
#include<utility/tagitem.h>
#include<graphics/text.h>
#include<graphics/rastport.h>
#include<intuition/screens.h>
#include<libraries/gadtools.h>
#include<libraries/asl.h>
#include<exec/memory.h>
#include<string.h>
#include<stdio.h>
#include<clib/exec_protos.h>
#include<clib/graphics_protos.h>
#include<clib/intuition_protos.h>
#include<clib/gadtools_protos.h>
#include<clib/asl_protos.h>
#include<clib/dos_protos.h>
/* The library base global variables */
/* (The different style of opening libraries requires these to be initialised to NULL) */
struct Library* GfxBase = NULL;
struct Library* IntuitionBase = NULL;
struct Library* GadToolsBase = NULL;
struct Library* AslBase = NULL;
struct Library* DosBase = NULL;
struct Library* IFFBase = NULL;
/* The global handle on the palette gadget */
struct Gadget* palgad = NULL;
/* Global record of foreground pen */
UBYTE pen;
/* Global records of our windows */
struct Window* drawwin = NULL;
struct Window* toolwin = NULL;
/* Global record of title bar height */
int offtop;
/* Global record of our menu strip */
struct Menu* menustrip = NULL;
/* Global record of the screen's visual information */
APTR vinfo = NULL;
/* Initialised structure declaration: describes 8pt Topaz font */
struct TextAttr topazFont = { "topaz.font", 8, 0, 0, };
/* Global record of our gadget list */
struct Gadget* glist = NULL;
/* Global record of our screen */
struct Screen* scr = NULL;
/* Global handles for our requesters */
struct FileRequester* loadreq = NULL;
struct FileRequester* savereq = NULL;
/* Global handle for our bitmap */
struct BitMap* bitmap = NULL;
/* Need to give prototypes for our functions */
int createAll();
void freeAll();
int openLibs();
void closeLibs();
int openScr();
void closeScr();
int createMenuStrip();
void freeMenuStrip();
int openToolWin();
void closeToolWin();
int openDrawWin();
void closeDrawWin();
int createGadgets();
void freeGadgets();
void handleIDCMP();
int checkToolWin();
void setFgPen(int);
void doGadgetUp(UWORD, struct Gadget*);
int doMenuPick(UWORD);
void freeReqs();
void load();
void save();
int createBitmap();
void freeBitmap();
/* Some constants for the position and size of our gadget */
#define MYBUT_LEFT (10)
#define MYBUT_TOP (5)
#define MYBUT_WIDTH (80)
#define MYBUT_HEIGHT (12)
#define MYBUT_TEXT "Next Pen"
#define MYBUT_ID (0)
#define MYPAL_LEFT (170)
#define MYPAL_TOP (1)
#define MYPAL_WIDTH (109)
#define MYPAL_HEIGHT (19)
#define MYPAL_TEXT "Colour:"
#define MYPAL_ID (1)
#define MYPAL_DEPTH (4)
/* The top gap required around the gadgets */
#define MYTOPGAP (21)
/* The initial pen colour */
#define MYINITPEN (1)
/* The size of our filename string */
#define MAXFILENAME (300)
/* The start of the program */
void main()
{
/* Use a different style of opening libraries... */
if(createAll())
{
/* Now do the real work */
handleIDCMP();
}
/* Matched call to close libraries */
freeAll();
}
int createAll()
{
return openLibs() && openScr() && createBitmap() && createMenuStrip() && createGadgets() && openToolWin() && openDrawWin();
}
void freeAll()
{
freeReqs();
closeDrawWin();
closeToolWin();
freeGadgets();
freeMenuStrip();
freeBitmap();
closeScr();
closeLibs();
}
/* Try to open all the libraries -- return TRUE on success */
int openLibs()
{
if((GfxBase = OpenLibrary("graphics.library",37)) == NULL)
{
printf("Error: could not open graphics.library\n");
return FALSE;
}
if((IntuitionBase = OpenLibrary("intuition.library",37)) == NULL)
{
printf("Error: could not open intuition.library\n");
return FALSE;
}
if((GadToolsBase = OpenLibrary("gadtools.library",37)) == NULL)
{
printf("Error: could not open gadtools.library\n");
return FALSE;
}
if((AslBase = OpenLibrary("asl.library",37)) == NULL)
{
printf("Error: could not open asl.library\n");
return FALSE;
}
if((DosBase = OpenLibrary("dos.library",37)) == NULL)
{
printf("Error: could not open dos.library\n");
return FALSE;
}
if((IFFBase = OpenLibrary("iff.library",23)) == NULL)
{
printf("Error: could not open iff.library\n");
return FALSE;
}
return TRUE;
}
/* Close any open library */
void closeLibs()
{
if(IFFBase)
CloseLibrary(IFFBase);
if(DosBase)
CloseLibrary(DosBase);
if(AslBase)
CloseLibrary(AslBase);
if(GadToolsBase)
CloseLibrary(GadToolsBase);
if(IntuitionBase)
CloseLibrary(IntuitionBase);
if(GfxBase)
CloseLibrary(GfxBase);
}
/* Open screen and setup GadTools stuff */
int openScr()
{
UWORD pens[] = { ~0 };
/* Try to open a new screen with 16 colours (four bitplanes deep) */
if(scr = OpenScreenTags(NULL,
SA_Depth, 4,
/* Enable 3D look by specifying SA_Pens */
SA_Pens, pens,
SA_Title, "Hello World Painter",
TAG_DONE))
{
/* Get the visual info so GadTools can render the gadgets nicely */
if(vinfo = GetVisualInfo(scr, TAG_DONE))
/* Succeeded */
return TRUE;
else
printf("Error: could not get visual info\n");
}
else
printf("Error: could not create screen\n");
/* Failed */
return FALSE;
}
void closeScr()
{
if(vinfo)
{
FreeVisualInfo(vinfo);
vinfo = NULL;
}
if(scr)
{
CloseScreen(scr);
scr = NULL;
}
}
/* Create the menu strip, using GadTools menu functions */
int createMenuStrip()
{
/* The description of our menus */
struct NewMenu mymenu[] =
{
{ NM_TITLE, "Project", 0, 0, 0, 0,},
{ NM_ITEM, "Load", "L", 0, 0, 0,},
{ NM_ITEM, "Save", "S", 0, 0, 0,},
{ NM_ITEM, NM_BARLABEL, 0, 0, 0, 0,},
{ NM_ITEM, "Quit", "Q", 0, 0, 0,},
{ NM_TITLE, "Pen", 0, 0, 0, 0,},
{ NM_ITEM, "Next", "N", 0, 0, 0,},
{ NM_ITEM, "Prev", "P", 0, 0, 0,},
{ NM_ITEM, NM_BARLABEL, 0, 0, 0, 0,},
{ NM_ITEM, "Reset", "R", 0, 0, 0,},
{ NM_TITLE, "Tools", 0, 0, 0, 0,},
{ NM_ITEM, "Screen Bar", "C", CHECKIT | MENUTOGGLE | CHECKED, 0, 0,},
{ NM_ITEM, "Tool Bar", "T", CHECKIT | MENUTOGGLE | CHECKED, 0, 0,},
{ NM_END, NULL, 0, 0, 0, 0,},
};
if (menustrip = CreateMenus(mymenu, TAG_END))
{
if (LayoutMenus(menustrip, vinfo, TAG_END))
/* Succeeded */
return TRUE;
else
printf("Error: could not layout menus\n");
}
else
printf("Error: could not create menu strip\n");
/* Failed */
return FALSE;
}
void freeMenuStrip()
{
if(menustrip)
{
FreeMenus(menustrip);
menustrip = NULL;
}
}
/* Actually open the windows, in the normal way */
int openToolWin()
{
/* Extra protection -- only open if not already open */
if(toolwin == NULL)
{
/* The minimal height of our tool window */
int h = MYTOPGAP + offtop + scr->WBorBottom;
/* Open our tool window */
if(toolwin = OpenWindowTags(NULL,
WA_Left, 0,
WA_Top, scr->Height - h,
/* Make the window sit in the bottom of the screen */
WA_Width, scr->Width,
WA_Height, h,
WA_Flags, WFLG_CLOSEGADGET | WFLG_DRAGBAR,
WA_IDCMP, IDCMP_CLOSEWINDOW | BUTTONIDCMP | IDCMP_REFRESHWINDOW | IDCMP_MENUPICK,
WA_Gadgets, glist,
WA_CustomScreen, scr,
WA_Title, "Tools",
TAG_DONE, 0))
{
/* Attach menu strip to tool window, as well */
if(SetMenuStrip(toolwin, menustrip))
{
/* Let GadTools refresh its bits of the tool window */
GT_RefreshWindow(toolwin, NULL);
return TRUE;
}
else
printf("Error: could not attach menus to tool window\n");
}
else
printf("Error: could not open tool window\n");
}
else
printf("Warning: tool window already open\n");
return FALSE;
}
void closeToolWin()
{
if(toolwin)
{
ClearMenuStrip(toolwin);
CloseWindow(toolwin);
toolwin = NULL;
}
}
int openDrawWin()
{
/* Open our drawing window */
if(drawwin = OpenWindowTags(NULL,
WA_Left, 0,
WA_Top, 0,
/* Make the window the same size as the screen */
WA_Width, scr->Width,
WA_Height, scr->Height,
WA_Flags, WFLG_BACKDROP | WFLG_BORDERLESS | WFLG_REPORTMOUSE | WFLG_SUPER_BITMAP,
WA_IDCMP, IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_MENUPICK,
WA_CustomScreen, scr,
WA_SuperBitMap, bitmap,
TAG_DONE, 0))
{
/* Clear our window, since our new bitmap may not be cleared already */
SetRast(drawwin->RPort, 0);
/* Set the drawing mode to draw only the foreground of text, not the background */
SetDrMd(drawwin->RPort, JAM1);
/* Attach menu strip to drawing window */
if(SetMenuStrip(drawwin, menustrip))
return TRUE;
else
printf("Error: could not attach menus to drawing window\n");
}
else
printf("Error: could not open drawing window\n");
return FALSE;
}
void closeDrawWin()
{
if(drawwin)
{
ClearMenuStrip(drawwin);
CloseWindow(drawwin);
drawwin = NULL;
}
}
int createGadgets()
{
struct Gadget* gad;
int offleft;
struct NewGadget newgad;
/* Start a GadTools gadget list */
gad = CreateContext(&glist);
/* The offsets of our window borders */
offleft = scr->WBorLeft;
offtop = scr->WBorTop + (scr->Font->ta_YSize + 1);
/* Setup our first gadget */
newgad.ng_TextAttr = &topazFont;
newgad.ng_VisualInfo = vinfo;
newgad.ng_LeftEdge = MYBUT_LEFT + offleft;
newgad.ng_TopEdge = MYBUT_TOP + offtop;
newgad.ng_Width = MYBUT_WIDTH;
newgad.ng_Height = MYBUT_HEIGHT;
newgad.ng_GadgetText = MYBUT_TEXT;
newgad.ng_GadgetID = MYBUT_ID;
newgad.ng_Flags = 0;
/* Now create it and add it to our list */
gad = CreateGadget(BUTTON_KIND, gad, &newgad, TAG_END);
/* Setup our second gadget */
/* (We can reuse newgad, and just change the different bits) */
newgad.ng_LeftEdge = MYPAL_LEFT + offleft;
newgad.ng_TopEdge = MYPAL_TOP + offtop;
newgad.ng_Width = MYPAL_WIDTH;
newgad.ng_Height = MYPAL_HEIGHT;
newgad.ng_GadgetText = MYPAL_TEXT;
newgad.ng_GadgetID = MYPAL_ID;
newgad.ng_Flags = 0;
/* Now create it and add it to our list */
gad = CreateGadget( PALETTE_KIND, gad, &newgad,
/* Initially selected pen */
GTPA_Color, MYINITPEN,
/* Depth: 2 to the power MYPAL_DEPTH colours */
GTPA_Depth, MYPAL_DEPTH,
/* Gadget will indicate selection */
GTPA_IndicatorWidth, 16,
TAG_DONE);
/* Remember gadget pointer so we can affect it in message handler */
palgad = gad;
/* Success if we managed final allocation */
return (gad != NULL);
}
void freeGadgets()
{
if(glist)
{
FreeGadgets(glist);
glist = NULL;
/* Reset palgad pointer, too */
palgad = NULL;
}
}
/* Our message handling code */
void handleIDCMP()
{
char* text = "Hello World!";
int going = TRUE;
int drawing = FALSE;
ULONG drawsig, toolsig, gotsig;
drawsig = 1 << drawwin->UserPort->mp_SigBit;
setFgPen(MYINITPEN);
while(going)
{
struct IntuiMessage* intuimsg;
/* Only include tool window signal mask if window is open */
toolsig = toolwin ? 1 << toolwin->UserPort->mp_SigBit : 0;
/* Wait for messages to arrive */
gotsig = Wait(drawsig | toolsig);
/* Messages have arrived: loop through all of them */
/* Check messages from the drawing window first */
if(gotsig & drawsig)
{
while(intuimsg = GT_GetIMsg(drawwin->UserPort))
{
/* Copy the important bits of the message */
ULONG class = intuimsg->Class;
UWORD code = intuimsg->Code;
WORD mousex = intuimsg->MouseX;
WORD mousey = intuimsg->MouseY;
/* Reply when finished copying bits from message */
GT_ReplyIMsg(intuimsg);
/* Act on this message... */
switch(class)
{
case IDCMP_MOUSEBUTTONS:
switch(code)
{
case SELECTDOWN:
drawing = TRUE;
break;
case SELECTUP:
drawing = FALSE;
break;
}
/* break; omitted so we draw on click, too */
case IDCMP_MOUSEMOVE:
if(drawing)
{
Move(drawwin->RPort, mousex, mousey);
Text(drawwin->RPort, text, strlen(text));
}
break;
case IDCMP_MENUPICK:
going = doMenuPick(code);
break;
}
}
}
/* Now check messages from the tool window */
if(going && (gotsig & toolsig))
{
while(toolwin && (intuimsg = GT_GetIMsg(toolwin->UserPort)))
{
/* Copy the important bits of the message */
ULONG class = intuimsg->Class;
UWORD code = intuimsg->Code;
APTR iaddr = intuimsg->IAddress;
/* Reply when finished copying bits from message */
GT_ReplyIMsg(intuimsg);
/* Act on this message... */
switch(class)
{
case IDCMP_CLOSEWINDOW:
{
struct MenuItem* item;
/* Close tool window */
closeToolWin();
/* Unset menu check mark */
/* First, remove menu strip from drawing window */
ClearMenuStrip(drawwin);
/* Menu 2, Item 1 is Tool Bar */
item = ItemAddress(menustrip, FULLMENUNUM(2,1,0));
/* Unset CHECKED flag */
item->Flags &= ~CHECKED;
/* Reattach menu strip to drawing window */
ResetMenuStrip(drawwin,menustrip);
break;
}
case IDCMP_REFRESHWINDOW:
/* You *MUST* remember to ask for and handle these refresh messages */
GT_BeginRefresh(toolwin);
GT_EndRefresh(toolwin, TRUE);
break;
case IDCMP_GADGETUP:
doGadgetUp(code, (struct Gadget*)iaddr);
break;
case IDCMP_MENUPICK:
going = doMenuPick(code);
break;
}
}
}
}
}
/* Set foreground pen of drawing window */
void setFgPen(int value)
{
/* Wrap when reached the end of the palette gadget's colours */
pen = value % (1<<MYPAL_DEPTH);
/* Only set pen if window is open */
if(drawwin)
SetAPen(drawwin->RPort, pen);
/* If the palette gadget has been made, update it with new pen value */
if(palgad)
GT_SetGadgetAttrs(palgad, toolwin, NULL, GTPA_Color, pen, TAG_DONE);
}
/* Process IDCMP_GADGETUP event */
void doGadgetUp(UWORD code, struct Gadget* gad)
{
switch(gad->GadgetID)
{
case MYBUT_ID:
/* Our button was clicked! Set foreground to next pen colour */
setFgPen(pen+1);
break;
case MYPAL_ID:
/* Our palette gadget was clicked! Set foreground to gadget colour */
setFgPen(code);
break;
}
}
/* Process IDCMP_MENUPICK event */
int doMenuPick(UWORD code)
{
UWORD menuCode, menuNumber, itemNumber;
/* Loop over all the menu selections in the menu code */
struct MenuItem* item;
for(menuCode = code;
menuCode != MENUNULL;
menuCode = item->NextSelect)
{
item = ItemAddress(menustrip, menuCode);
/* Extract the menu number and menu item number from the menu code */
menuNumber = MENUNUM(menuCode);
itemNumber = ITEMNUM(menuCode);
/* Now decide what to do based on what menu item was selected */
switch(menuNumber)
{
case 0: /* Project menu */
/* Only one item: Quit */
switch(itemNumber)
{
case 0: /* Load */
load();
break;
case 1: /* Save */
save();
break;
case 3: /* Quit (item 2 is the bar!) */
return FALSE;
}
break;
case 1: /* Pen menu */
switch(itemNumber)
{
case 0: /* Next */
setFgPen(pen+1);
break;
case 1: /* Prev */
setFgPen(pen-1);
break;
case 3: /* Reset (item 2 is the bar!) */
setFgPen(MYINITPEN);
break;
}
break;
case 2: /* Tools menu */
switch(itemNumber)
{
case 0: /* Screen Bar */
ShowTitle(scr, item->Flags & CHECKED);
break;
case 1: /* Tool Bar */
/* Do the open or close */
if(item->Flags & CHECKED)
{
/* If the open fails, stop immediately */
if(!openToolWin())
return FALSE;
}
else
closeToolWin();
break;
}
}
}
/* Keep going */
return TRUE;
}
/* Open an ASL load file requester */
void load()
{
/* Allocate the requester if we haven't already */
if(loadreq == NULL)
loadreq = (struct FileRequester*)AllocAslRequest(ASL_FileRequest,NULL);
if(loadreq)
{
if(AslRequestTags(loadreq,
ASLFR_TitleText, "Load File",
ASLFR_Window, drawwin,
ASLFR_Flags1, FRF_DOPATTERNS,
ASLFR_InitialPattern, "#?.iff",
TAG_DONE))
{
char filename[MAXFILENAME];
/* Create complete filename from ASL's dir and file */
strcpy(filename, loadreq->rf_Dir);
if(AddPart(filename, loadreq->rf_File, MAXFILENAME))
{
IFFL_HANDLE handle;
/* Try to open the IFF file */
if(handle = IFFL_OpenIFF(filename, IFFL_MODE_READ))
{
LONG count;
UWORD colortable[256];
/* Get colour information and change screen colours */
count = IFFL_GetColorTab(handle, colortable);
LoadRGB4(&(scr->ViewPort), colortable, count);
/* If we can load the picture, update window's display */
if(IFFL_DecodePic(handle, bitmap))
CopySBitMap(drawwin->WLayer);
else
printf("Error: could not decode IFF picture\n");
IFFL_CloseIFF(handle);
}
else
printf("Error: could not open IFF file\n");
}
else
printf("Error: could not make filename\n");
}
/* else: requester was cancelled */
}
else
printf("Error: could not allocate ASL (load) file request\n");
}
/* Open an ASL save file requester */
void save()
{
/* Another way of saying "allocate if we haven't already" */
if(savereq || (savereq = (struct FileRequester*)AllocAslRequest(ASL_FileRequest,NULL)))
{
if(AslRequestTags(savereq,
ASLFR_TitleText, "Save File",
ASLFR_Window, drawwin,
ASLFR_Flags1, FRF_DOPATTERNS | FRF_DOSAVEMODE,
ASLFR_InitialPattern, "#?.iff",
ASLFR_InitialFile, "picture.iff",
TAG_DONE))
{
char filename[MAXFILENAME];
/* Create complete filename from ASL's dir and file */
strcpy(filename, savereq->rf_Dir);
if(AddPart(filename, savereq->rf_File, MAXFILENAME))
{
/* Make sure our bitmap is the same as the display */
SyncSBitMap(drawwin->WLayer);
/* Try saving our bitmap, using the screen's colours */
if(IFFL_SaveBitMap(filename, bitmap,
scr->ViewPort.ColorMap->ColorTable,
IFFL_COMPR_BYTERUN1) == 0)
printf("Error: could not write IFF picture\n");
}
else
printf("Error: could not make filename\n");
}
/* else: requester was cancelled */
}
else
printf("Error: could not allocate ASL (save) file request\n");
}
/* Free any requesters that may have been allocated */
void freeReqs()
{
if(loadreq)
{
FreeAslRequest(loadreq);
loadreq = NULL;
}
if(savereq)
{
FreeAslRequest(savereq);
savereq = NULL;
}
}
int createBitmap()
{
/* The MEMF_CLEAR flag is vital, since it zeroes the allocated memory. */
/* Thus the pointers in the bitmap will be NULL, if we don't manage to */
/* allocate them properly. */
if(bitmap = AllocMem(sizeof(struct BitMap), MEMF_PUBLIC | MEMF_CLEAR))
{
int plane;
InitBitMap(bitmap, scr->BitMap.Depth, scr->Width, scr->Height);
for(plane = 0; plane < scr->BitMap.Depth; plane++)
{
bitmap->Planes[plane] = AllocRaster(scr->Width, scr->Height);
if(bitmap->Planes[plane] == NULL)
return FALSE;
}
/* If we get here, we succeeded. */
return TRUE;
}
else
return FALSE;
}
void freeBitmap()
{
if(bitmap)
{
int plane;
for(plane = 0; plane < scr->BitMap.Depth; plane++)
{
if(bitmap->Planes[plane])
FreeRaster(bitmap->Planes[plane], scr->Width, scr->Height);
}
FreeMem(bitmap, sizeof(struct BitMap));
bitmap = NULL;
}
}